class AsyncFilterChain {
  #filters = [];
  #i = 0;

  addFilters(...filters) {
    if (filters) {
      this.#filters.push(...filters);
    }
  }

  async doFilter(t) {
    if (this.#i < this.#filters.length) {
      const filter = this.#filters[this.#i++];
      await filter(t, this);
    }
  }
}

const f1 = async (so, chain) => {
  so.value += '1';
  await chain.doFilter(so);
  so.value += 'a';
};

const f2 = async (so, chain) => {
  so.value += '2';
  // 注意，这里不 chain 了
  so.value += 'b';
};

const f3 = async (so, chain) => {
  so.value += '3';
  await chain.doFilter(so);
  so.value += 'c';
};

(async () => {
  const chain = new AsyncFilterChain();
  chain.addFilters(f1, f2, f3);

  const so = { value: 'x' };
  await chain.doFilter(so);

  console.log(so.value === 'x12ba');
})();
